﻿using System;
using System.ServiceModel;
using System.Xml.Linq;
using CPN.PJN.Silverlight.Common.Logging.LoggerReference;

namespace CPN.PJN.Silverlight.Common.Logging.LogListeners
{
    /// <summary>
    /// Cette classe représente une implémentation des logs pour appeler le service de log WCF
    /// </summary>
    public class LogServiceListener : LogListener
    {
        #region Const
        
        /// <summary>
        /// Nom  de la configuration du EndPoint 
        /// </summary>
        public const string DEFAULT_ENDPOINT_CONFIGURATION = "LoggingServiceEndPoint";

        /// <summary>
        ///Catégorie gloable pour les logs serveur
        /// </summary>
        public const string DEFAULT_CATEGORY_NAME = "General.Client";

        #endregion

        #region Private Members
        
        /// <summary>
        /// Client Service de logs
        /// </summary>
        private LoggerServiceClient client; 

        #endregion

        #region EndPointName Property

        /// <summary>
        /// Nom du EndPoint à utiliser
        /// </summary>
        public string EndPointName { get; private set; }
        
        #endregion

        #region EndPointAddress Property

        /// <summary>
        /// Addresse Url du EndPoint à utiliser
        /// </summary>
        public string EndPointAddress { get; private set; }
        
        #endregion

        #region ServerCategoryName Property
        
        /// <summary>
        /// Nom de la catégorie coté serveur
        /// </summary>
        public string ServerCategoryName { get; private set; } 

        #endregion

        #region Constructor
        
        /// <summary>
        /// Constructeur par défaut
        /// </summary>
        public LogServiceListener()
        {
        }

        #endregion

        #region Configure Method

        /// <summary>
        /// Configuration du gestionnaire
        /// </summary>
        /// <param name="configurationElement">Element de configuration</param>
        public override void Configure(XElement configurationElement)
        {
            if (configurationElement.Attribute("formatterType") != null)
            {
                var nameType = configurationElement.Attribute("formatterType").Value;
                var type = Type.GetType(nameType);
                if (type != null)
                {
                    this.Formatter = Activator.CreateInstance(type) as LogFormatter;
                }
            }
            if (configurationElement.Attribute("name") != null)
            {
                this.Name = configurationElement.Attribute("name").Value;
            }

            if (configurationElement.Attribute("serverCategoryName") != null)
            {
                this.ServerCategoryName = configurationElement.Attribute("serverCategoryName").Value;
            }
            else
            {
                this.ServerCategoryName = DEFAULT_CATEGORY_NAME;
            }

            if (configurationElement.Attribute("endPointName") != null)
            {
                this.EndPointName = configurationElement.Attribute("endPointName").Value;
            }
            else
            {
                this.EndPointName = DEFAULT_ENDPOINT_CONFIGURATION;
            }

            if (configurationElement.Attribute("endPointAddress") != null)
            {
                this.EndPointAddress = configurationElement.Attribute("endPointAddress").Value;
            }
            
            if (!string.IsNullOrEmpty(this.EndPointName))
            {
                this.client = new LoggerServiceClient(this.EndPointName);
                if (!string.IsNullOrEmpty(this.EndPointAddress))
                {
                    this.client.Endpoint.Address = new EndpointAddress(this.EndPointAddress);
                }
            }
        }

        #endregion
        
        #region Write Methods

        /// <summary>
        /// Cette méthode écrit le message de log dans une catégorie précise
        /// </summary>
        /// <param name="message">Message de log</param>
        /// <param name="category">Catégorie de log</param>
        public override void Write(object message, string category)
        {
            this.client.WriteWithCategoryAsync(this.Formatter.Format(category, message), this.ServerCategoryName);
        }

        /// <summary>
        /// Cette méthode écrit le message de log dans une catégorie précise et sa severité
        /// </summary>
        /// <param name="message">Message de log</param>
        /// <param name="category">Catégorie de log</param>
        /// <param name="severity">severité</param>
        public override void Write(object message, string category, int severity)
        {
            this.client.WriteWithSeverityAsync(this.Formatter.Format(category, message), this.ServerCategoryName, severity);
        }

        /// <summary>
        /// Cette méthode écrit le message de log dans une catégorie précise et sa severité
        /// </summary>
        /// <param name="message">Message de log</param>
        /// <param name="category">Catégorie de log</param>
        /// <param name="severity">severité</param>
        /// <param name="data">données supplémentaires à afficher</param>
        public override void Write(object message, string category, int severity, params object[] data)
        {
            this.client.WriteWithSeverityAsync(this.Formatter.Format(category, message), this.ServerCategoryName, severity);
        }

        #endregion

    }
}
